package com.copy.core;

import com.copy.pojo.BeanMetaData;
import com.copy.pojo.BeanMethod;
import com.copy.scan.ScanBasePackageStrategy;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
 * author: liziyun
 * date: 2019-9-30
 * email: root@ofo.email
 * describe: 流程控制
 *      模板方法模式，控制整个框架的执行流程
 *
 */
public abstract class AbstractApplicationContext implements Application {

    protected String basePackage;
    //scan
    protected Set<Class<?>> annotationClass = new HashSet<>();
    //parse
    protected Map<Class, BeanMetaData> beanMetaDataMap = new ConcurrentHashMap<>();
    //proxy
    protected Map<Class,Object> proxyBeans = new ConcurrentHashMap<>();
    //脱离Spring,自定义扫描器.  默认:整合Spring,这个成员属性为null
    protected ScanBasePackageStrategy scanBasePackageStrategy ;
    //默认是null,因为整合Spring.
    public AbstractApplicationContext(ScanBasePackageStrategy scanBasePackageStrategy) {
        this.scanBasePackageStrategy = scanBasePackageStrategy;
    }

    public void refresh(){
        try {
            //扫描
            if (scanBasePackageStrategy==null){
                annotationClass = scannerPackages(basePackage);
            }else{
                annotationClass = scanBasePackageStrategy.scannerPackages(basePackage);
            }
            //解析
            parser();
            //映射
            propertyMapping();
            //创建代理
            createProxy();
        }catch (Exception e){
            System.out.println("=====================EasyCopy启动失败=====================");
            System.out.println(e.getMessage());
            e.printStackTrace();
            System.out.println("=====================EasyCopy启动失败=====================");
        }

    }
    public void parser(){
        Iterator<Class<?>> classes = annotationClass.iterator();
        while (classes.hasNext()){
            Class cls = classes.next();
            BeanMetaData beanDefinition = getBeanDefinition(cls);
            beanMetaDataMap.put(cls,beanDefinition);
        }
    }
    public void propertyMapping(){
        for (Class c : annotationClass) {
            //获取类元数据
            BeanMetaData beanMetaData = beanMetaDataMap.get(c);
            //获取方法元数据
            Collection<BeanMethod> methodBeans = beanMetaData.getBeanMethods().values();
            for (BeanMethod methodBean : methodBeans) {
                //属性映射：提前实例化对象 --》方法两个参数
                if (methodBean.isOpenParam()){
                    getMethodMetadaByParamMaps(methodBean);
                }else if (methodBean.isClone()){
                    getMethodMetadaByClone(methodBean);
                }else{//属性映射:未提前实例化对象 --》方法一个参数
                    getMethodMetadaByAuto(methodBean);
                }
            }
        }
    }
    public void createProxy() throws Exception {
        for (Class cls : annotationClass) {
            Object proxyBean = createProxyBean(cls,beanMetaDataMap.get(cls) );
            proxyBeans.putIfAbsent(cls,proxyBean);
        }
    }
}
